﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using Ue.Framework.Data;
using Ue.Infrastructure;
using Ue.Infrastructure.DomainBase;
using Ue.Infrastructure.RepositoryFramework.Repository;
using Ue.Qcdz.Domain.Membership;
using Ue.Qcdz.Domain.Permissions;
using Ue.Qcdz.Domain.Roles;
using Ue.Qcdz.Domain.TheResource;
using Ue.Qcdz.UI.Controls.Roles;

namespace Ue.Qcdz.Repositories.Roles
{
    public class RoleRepository : SqlServerRepository<Role>, IRoleRepository
    {
        public RoleRepository()
            : this(null) { }

        public RoleRepository(IUnitOfWork uniteOfWork)
            : base(uniteOfWork)
        {

        }
        protected override string GetDataTableName()
        {
            return "Roles";
        }

        protected override string GetKeyFieldName()
        {
            return RoleFactory.FieldNames.EntityKey;
        }

        protected override string[] GetBaseInsertFields()
        {
            return new string[]{
                RoleFactory.FieldNames.EntityKey,
                RoleFactory.FieldNames.Name
            };
        }

        protected override string[] GetBaseUpdateFields()
        {
            return new string[]{
                RoleFactory.FieldNames.Name
            };
        }

        protected override IDataParameter[] BuildParameters(Role entity)
        {
            return new IDataParameter[]{
                this.RepositoryDriver.BuildParameter(RoleFactory.FieldNames.EntityKey,entity.Key),
                this.RepositoryDriver.BuildParameter(RoleFactory.FieldNames.Name,entity.Name)
            };
        }

        protected override string GetOrderBy()
        {
            return null;
        }
        protected override void PersistNewItem(Role item)
        {
            base.PersistNewItem(item);
            if (item.PermissionList.Count > 0)
            {
                InsertPermission(item);
            }
            if (item.ResourceList.Count > 0)
            {
                InsertResource(item);
            }

        }

        private void InsertPermission(Role item)
        {
            var query = "INSERT INTO RoleInPermissions(RoleId,PermissionId)VALUES(@RoleId,@PermissionId)";
            if (item.ResourceList != null && item.PermissionList.Count > 0)
            {

                foreach (Permission permission in item.PermissionList)
                {
                    RepositoryDriver.ExecuteNonQuery(
                        this.RepositoryDriver.BuildCommand(
                            query,
                            this.RepositoryDriver.BuildParameter(RoleFactory.FieldNames.PermissionFieldNames.RoleId,
                                                                 item.Key),
                            this.RepositoryDriver.BuildParameter(
                                RoleFactory.FieldNames.PermissionFieldNames.PermissionsId, permission.Key)
                            ));
                }
            }
        }
        void InsertResource(Role item)
        {

            if (item.ResourceList != null && item.ResourceList.Count > 0)
            {
                foreach (var resource in item.ResourceList)
                {
                    var query = "INSERT INTO RoleInResource(RoleId,ResourceId)VALUES(@RoleId,@ResourceId)";
                    RepositoryDriver.ExecuteNonQuery(
                        this.RepositoryDriver.BuildCommand(
                            query,
                            this.RepositoryDriver.BuildParameter(RoleFactory.FieldNames.PermissionFieldNames.RoleId,
                                                                 item.Key),
                            this.RepositoryDriver.BuildParameter(RoleFactory.FieldNames.ResourceId, resource.Key)
                            ));
                }
            }

        }

        protected override IWhereClause BuildWhereClauseBy(IDataQuery dataQuery)
        {
            RolesGridView rolesGridView = dataQuery as RolesGridView;
            if (rolesGridView != null)
            {
                return new UserWhereClause(rolesGridView);

            }
            return null;
        }
        protected override void PersistDeletedItem(Role item)
        {
            DeleteRelation(item);
            base.PersistDeletedItem(item);

        }

        protected override void PersistUpdatedItem(Role item)
        {
            base.PersistUpdatedItem(item);
            DeleteRelation(item);
            if (item.PermissionList.Count > 0)
            {
                InsertPermission(item);
            }
            if (item.ResourceList.Count > 0)
            {
                InsertResource(item);
            }


        }
        private void DeleteRelation(Role item)
        {
            var query = "delete from roleinpermissions where roleid=@roleid;delete from RoleInResource where roleid=@roleid;";
            RepositoryDriver.ExecuteNonQuery(
                 this.RepositoryDriver.BuildCommand(
                    query,
                    this.RepositoryDriver.BuildParameter(RoleFactory.FieldNames.PermissionFieldNames.RoleId, item.Key)

                    ));
            InsertPermission(item);
        }

        protected override IDictionary<string, SqlServerRepositoryBase<Role>.ChildDataHandler> GetBuildEntityChildCallbacks()
        {
            var callBacks = new Dictionary<string, SqlServerRepository<Role>.ChildDataHandler>();

            callBacks.Add(RoleFactory.FieldNames.EntityKey, delegate(Role role, object objectValue)
                                                                {
                                                                    IPermissionsRepository permissionsRepository =
                                                                        Ue.Infrastructure.RepositoryFramework.
                                                                            RepositoryFactory.GetRepository
                                                                            <IPermissionsRepository, Permission>();
                                                                    role.PermissionList = (List<Permission>)permissionsRepository.FindBy(role);
                                                                    IResourceRepository resourceRepository =
                                                                       Ue.Infrastructure.RepositoryFramework.
                                                                           RepositoryFactory.GetRepository
                                                                           <IResourceRepository, Resource>();
                                                                    role.ResourceList = (List<Resource>)resourceRepository.FindBy(role);
                                                                });


            return callBacks;
        }
        public class UserWhereClause : IWhereClause
        {
            public RolesGridView rolesGridView;
            #region Implementation of IWhereClause
            public UserWhereClause(RolesGridView rolesGridView)
            {
                this.rolesGridView = rolesGridView;
            }

            public string Clause
            {
                get
                {
                    var clause = "Name LIKE '%'+@Name+'%'";
                    return clause;
                }
            }

            public IDataParameter[] Parameters
            {
                get
                {
                    string strName = rolesGridView.Name;
                    if (string.IsNullOrEmpty(strName)) strName = "";
                    var Parameters = new IDataParameter[]
                                         {
                                             SqlServerDriver.Instance.BuildParameter(RoleFactory.FieldNames.Name,
                                                                                     strName)

                                         };
                    return Parameters;
                }
            }

            #endregion
        }
        #region Implementation of IRoleRepository

        public IList<Role> GetRoleList(User user)
        {
            var query =
                "SELECT * FROM Roles WHERE EXISTS(SELECT * FROM UserInRoles WHERE UserInRoles.RoleId=Roles.Id AND UserInRoles.UserId=@UserId)";
            return this.BuildEntitiesFromSql(query, this.RepositoryDriver.BuildParameter("@UserId", user.Key));
        }
        public void DeleUserRole(string userId)
        {
            var query = "DELETE FROM UserInRoles WHERE UserId=@UserId";
            RepositoryDriver.ExecuteNonQuery(
                 this.RepositoryDriver.BuildCommand(
                    query,
                    this.RepositoryDriver.BuildParameter("UserId", userId)
                    ));
        }

        public void AddInUserRole(List<Role> roleList, string userId)
        {
            DeleUserRole(userId);
            var query = "INSERT INTO UserInRoles(UserId,RoleId) VALUES(@UserId,@RoleId)";
            foreach (var role in roleList)
            {
                RepositoryDriver.ExecuteNonQuery(
                 this.RepositoryDriver.BuildCommand(
                    query,
                    this.RepositoryDriver.BuildParameter(RoleFactory.FieldNames.PermissionFieldNames.RoleId, role.Key),
                    this.RepositoryDriver.BuildParameter("UserId", userId)
                    ));
            }

        }

        public Role FindBy(string roleName)
        {
            const string query = "SELECT * FROM Roles WHERE Name = @Name";
            var parameter = new IDataParameter[]
                                             {
                                                 this.RepositoryDriver.BuildParameter(RoleFactory.FieldNames.Name,
                                                                                      roleName)
                                                               
            };
            return BuildEntityFromSql(query, parameter);
        }



        #endregion
    }
}
